package com.yunchao.test.presentation.screen

import androidx.lifecycle.viewModelScope
import com.yunchao.feature.base.data.CustomAudioManager
import com.yunchao.feature.base.domain.result.errorMsg
import com.yunchao.feature.base.presentation.viewmodel.BaseAction
import com.yunchao.feature.base.presentation.viewmodel.BaseEffect
import com.yunchao.feature.base.presentation.viewmodel.BaseState
import com.yunchao.feature.base.presentation.viewmodel.BaseViewModel
import com.yunchao.library.lock.LockEPCInfo
import com.yunchao.library.lock.getLockStatus
import com.yunchao.test.domain.model.LockToolModel
import com.yunchao.test.domain.model.VoucherTypeModel
import com.yunchao.test.domain.repository.LockToolRepository
import com.yunchao.test.domain.repository.MaintenanceInfoRepository
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.isActive
import kotlinx.coroutines.launch
import timber.log.Timber
import java.io.File

internal class MainViewModel(
    private val lockToolRepository: LockToolRepository,
    private val maintenanceInfoRepository: MaintenanceInfoRepository,
    private val customAudioManager: CustomAudioManager
) :
    BaseViewModel<MainViewModel.UiState, MainViewModel.Action, MainViewModel.UiEffect>(
        UiState.Idle
    ) {
    private var loopJob: Job? = null
    private var currentLockEPCInfo: LockEPCInfo? = null


    fun getMaintenanceFileList() = viewModelScope.launch {
        maintenanceInfoRepository.getMaintenanceFileList()
            .onSuccess {
                postSideEffect(UiEffect.FileList(it))
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(2)
                }
            }
    }

    fun handleMaintenanceFile(fileName: String) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        maintenanceInfoRepository.addMaintenanceInfoList(fileName)
            .onFailure {
                Timber.e(it)
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(2)
                }
            }
            .onSuccess {
                postSideEffect(UiEffect.ShowToast("数据导入成功")).apply {
                    customAudioManager.playSound(1)
                }
            }
    }

    fun openDevice() = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.openDevice()
            .onSuccess {
                postSideEffect(UiEffect.ShowToast("设备初始化成功")).apply {
                    customAudioManager.playSound(
                        1
                    )
                }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }

    fun inventoryOnce() = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.inventoryOnce()
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it))
                    .apply {
                        if (it.message == null) {
                            postSideEffect(UiEffect.HideLoading)
                        } else {
                            postSideEffect(UiEffect.ShowToast(it.message))
                        }
                    }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }

    fun activeLock(lockEPCInfo: LockEPCInfo, voucherTypeModel: VoucherTypeModel) =
        viewModelScope.launch {
            postSideEffect(UiEffect.ShowLoading)
            lockToolRepository.activeLock(lockEPCInfo, voucherTypeModel)
                .onSuccess {
                    sendAction(Action.GetLockToolModelInfo(it)).apply {
                        postSideEffect(
                            UiEffect.HideLoading
                        )
                    }.apply { customAudioManager.playSound(1) }
                }
                .onFailure {
                    postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                        customAudioManager.playSound(
                            2
                        )
                    }
                }
        }

    fun openLockWriteLogistics(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.openLockWriteLogistics(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }


    fun loopOpenCloseLock(lockEPCInfo: LockEPCInfo) {
        if (loopJob?.isActive == true) {
            return // 如果循环已经在运行，直接返回
        }
        currentLockEPCInfo = lockEPCInfo
        loopJob = viewModelScope.launch {
            while (isActive) {
                postSideEffect(UiEffect.ShowLoading)
                currentLockEPCInfo?.let {
                    if (it.getLockStatus() == "00") {
                        lockToolRepository.closeLockWriteLogistics(it)
                    } else {
                        lockToolRepository.openLockWriteLogistics(it)
                    }
                }?.onFailure {
                    postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                        customAudioManager.playSound(
                            2
                        )
                    }
                }?.onSuccess {
                    currentLockEPCInfo = it.handleAfterLockEPCInfo
                    sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                        .apply { customAudioManager.playSound(1) }
                }
                delay(1000)
            }
        }
    }

    fun stopLoopOpenCloseLock() {
        loopJob?.cancel()
        loopJob = null
    }

    fun closeLockWriteLogistics(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.closeLockWriteLogistics(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }


    fun openLock(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.openLock(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }

    fun closeLock(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.closeLock(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }


    fun recoveryLock(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.recoveryLock(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }

    fun cleanLock(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.cleanLock(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }
    }

    fun readLockLogisticsLog(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.readLockLogisticsLog(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }

    }

    fun readLockLog(lockEPCInfo: LockEPCInfo, start: Int, number: Int) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.readLockLog(lockEPCInfo, start, number)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }

    }

    fun readLockLogCount(lockEPCInfo: LockEPCInfo) = viewModelScope.launch {
        postSideEffect(UiEffect.ShowLoading)
        lockToolRepository.readLockLogCount(lockEPCInfo)
            .onSuccess {
                sendAction(Action.GetLockToolModelInfo(it)).apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }
            .onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg)).apply {
                    customAudioManager.playSound(
                        2
                    )
                }
            }

    }


    fun closeDevice() = viewModelScope.launch {
        lockToolRepository.closeDevice()
    }


    override fun onCleared() {
        super.onCleared()
        closeDevice()
    }

    internal sealed interface Action : BaseAction<UiState> {
        class GetLockToolModelInfo(private val data: LockToolModel) : Action {
            override fun reduce(state: UiState) = UiState.Content(data)
        }
    }

    internal sealed interface UiState : BaseState {
        data class Content(val data: LockToolModel) : UiState
        data object Idle : UiState
    }

    internal sealed interface UiEffect : BaseEffect {
        data class FileList(val list: List<File>) : UiEffect
        data object ShowLoading : UiEffect
        data object HideLoading : UiEffect
        data class ShowToast(val msg: String) : UiEffect
    }
}